﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sausage.Common;
using Sausage.Web.DataModel;
using Sausage.Web.Models;

namespace Sausage.Web.Domain
{
    public class FileUploadHelper 
    {
        public static bool UploadFile(UploadFileModel data, HttpFileCollectionBase files, out Guid fileID)
        {
            if (files.Count > 0)
            {
                try
                {
                    //Save the file.
                    FileInfo fileInfo;
                    SaveFile(data, files[0], out fileID, out fileInfo);

                    //Update database.
                    UpdateDatabase(fileID, data, fileInfo);
                    return true;
                }
                catch
                {
                    fileID = Guid.Empty;
                    return false;
                }
            }

            fileID = Guid.Empty;
            return false;
        }

        private static void SaveFile(UploadFileModel data, HttpPostedFileBase file, out Guid fileID, out FileInfo fileInfo)
        {
            //Build file path, and saving environment.
            fileInfo = new FileInfo(file.FileName);
            string saveFolder = HttpContext.Current.Server.MapPath(GetTargetFolderByFileType(data));

            if (!Directory.Exists(saveFolder))
                Directory.CreateDirectory(saveFolder);

            fileID = Guid.NewGuid();
            string savePath = string.Concat(saveFolder, Path.DirectorySeparatorChar, fileID.ToString(), fileInfo.Extension);

            //Save file to disk.
            if (File.Exists(savePath))
                File.Delete(savePath);

            bool saved = false;

            if (Utility.IsScalePhoto)
            {
                Bitmap sourceImage;
                Bitmap targetImage;
                try
                {
                    sourceImage = new Bitmap(file.InputStream);
                    int width = 0;
                    int height = 0;
                    bool needScale = false;

                    if (sourceImage.Height > Utility.ScalePhotoHeight)
                    {
                        height = Utility.ScalePhotoHeight;
                        width = (int) ((decimal) Utility.ScalePhotoHeight/(decimal) sourceImage.Height*
                                       (decimal) sourceImage.Width);
                        needScale = true;
                    }
                    else if (sourceImage.Width > Utility.ScalePhotoWidth)
                    {
                        width = Utility.ScalePhotoWidth;
                        height =
                            (int)
                            ((decimal) Utility.ScalePhotoWidth/(decimal) sourceImage.Width*(decimal) sourceImage.Height);
                        needScale = true;
                    }

                    if (needScale)
                    {
                        targetImage = new Bitmap(sourceImage, width, height);
                        targetImage.Save(savePath, sourceImage.RawFormat);
                        saved = true;
                    }
                }
                catch
                {
                    //do nothing.
                }
            }

            if(!saved)
                file.SaveAs(savePath); // save the file.
        }

        public static void MoveFileFromTempToProjectAttachment(Guid projectID, Guid[] attachments)
        {
            using (var context = new SausageEntities())
            {
                var targetFolder = HttpContext.Current.Server.MapPath(Utility.ProjectFolder);
                if (!Directory.Exists(targetFolder))
                    Directory.CreateDirectory(targetFolder);
                var sourceFolder = HttpContext.Current.Server.MapPath(Utility.TempFileFolder);
                var list = context.UploadTempFile.Where(item => attachments.Contains(item.FileID)).ToList();

                foreach (var uploadTempFile in list)
                {
                    string sourcePath = string.Concat(sourceFolder,
                                                        Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                        uploadTempFile.FileExtension);

                    string targetPath = string.Concat(targetFolder,
                                                        Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                        uploadTempFile.FileExtension);

                    if (File.Exists(sourcePath))
                    {
                        File.Move(sourcePath, targetPath);    
                        var attachment = new ProjectAttachment();
                        attachment.AttachmentID = uploadTempFile.FileID;
                        attachment.ProjectID = projectID;
                        attachment.OrganizationID = Helper.CurrentPrincipal.User.OrganizationID;
                        attachment.AttachmentName = uploadTempFile.FileName.Trim();
                        attachment.FileExtension = uploadTempFile.FileExtension;
                        attachment.IsOpen = uploadTempFile.IsOpen.HasValue && uploadTempFile.IsOpen.Value;
                        context.AddToProjectAttachment(attachment);
                    }
                    context.DeleteObject(uploadTempFile);
                }

                context.SaveChanges();
            }
            
            CleanDirtyFile();
        }

        public static void MoveFileFromTempToMaintainPhoto(Guid journalID, Guid[] photos)
        {
            using (var context = new SausageEntities())
            {
                var targetFolder = HttpContext.Current.Server.MapPath(Utility.MaintainJournalFolder);
                if (!Directory.Exists(targetFolder))
                    Directory.CreateDirectory(targetFolder);
                var sourceFolder = HttpContext.Current.Server.MapPath(Utility.TempFileFolder);
                var list = context.UploadTempFile.Where(item => photos.Contains(item.FileID)).ToList();

                foreach (var uploadTempFile in list)
                {
                    string sourcePath = string.Concat(sourceFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);

                    string targetPath = string.Concat(targetFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);
                    if (File.Exists(sourcePath))
                    {
                        File.Move(sourcePath, targetPath);
                        var maintainPhoto = new MaintainPhoto();
                        maintainPhoto.PhotoID = uploadTempFile.FileID;
                        maintainPhoto.JournalID = journalID;
                        maintainPhoto.PhotoName = uploadTempFile.FileName.Trim();
                        maintainPhoto.FileExtension = uploadTempFile.FileExtension;
                        maintainPhoto.Memo = uploadTempFile.Memo;
                        context.AddToMaintainPhoto(maintainPhoto);
                    }

                    context.DeleteObject(uploadTempFile);
                }
                context.SaveChanges();
            }

            CleanDirtyFile();
        }

        public static void MoveFileFromTempToProjectPhoto(Guid journalID, Guid[] photos)
        {
            using (var context = new SausageEntities())
            {
                var targetFolder = HttpContext.Current.Server.MapPath(Utility.ProjectJournalFolder);
                if (!Directory.Exists(targetFolder))
                    Directory.CreateDirectory(targetFolder);
                var sourceFolder = HttpContext.Current.Server.MapPath(Utility.TempFileFolder);

                var list = context.UploadTempFile.Where(item => photos.Contains(item.FileID)).ToList();
                foreach (var uploadTempFile in list)
                {
                    string sourcePath = string.Concat(sourceFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);

                    string targetPath = string.Concat(targetFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);
                    if (File.Exists(sourcePath))
                    {
                        File.Move(sourcePath, targetPath);

                        var projectPhoto = new ProjectPhoto();
                        projectPhoto.PhotoID = uploadTempFile.FileID;
                        projectPhoto.JournalID = journalID;
                        projectPhoto.PhotoName = uploadTempFile.FileName.Trim();
                        projectPhoto.FileExtension = uploadTempFile.FileExtension;
                        projectPhoto.Memo = uploadTempFile.Memo;
                        context.AddToProjectPhoto(projectPhoto);
                    }

                    context.DeleteObject(uploadTempFile);
                }
                context.SaveChanges();
            }
 
            CleanDirtyFile();
        }

        public static void MoveFileFromTempToEmergencyAttachment(Guid emergencyID, Guid[] attachments)
        {
            using (var context = new SausageEntities())
            {
                var targetFolder = HttpContext.Current.Server.MapPath(Utility.EmergencyFolder);
                if (!Directory.Exists(targetFolder))
                    Directory.CreateDirectory(targetFolder);

                var sourceFolder = HttpContext.Current.Server.MapPath(Utility.TempFileFolder);

                var list = context.UploadTempFile.Where(item => attachments.Contains(item.FileID)).ToList();
                foreach (var uploadTempFile in list)
                {
                    string sourcePath = string.Concat(sourceFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);

                    string targetPath = string.Concat(targetFolder,
                                                      Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                      uploadTempFile.FileExtension);
                    if (File.Exists(sourcePath))
                    {
                        File.Move(sourcePath, targetPath);

                        var emergencyAttachment = new EmergencyAttachment();
                        emergencyAttachment.AttachmentID = uploadTempFile.FileID;
                        emergencyAttachment.EmergencyID = emergencyID;
                        emergencyAttachment.AttachmentName = uploadTempFile.FileName.Trim();
                        emergencyAttachment.FileExtension = uploadTempFile.FileExtension;
                        context.AddToEmergencyAttachment(emergencyAttachment);
                    }

                    context.DeleteObject(uploadTempFile);
                }
                context.SaveChanges();
            }

            CleanDirtyFile();
        }


        private static string GetTargetFolderByFileType(UploadFileModel data)
        {
            if (!data.OwnerID.HasValue)
                return Utility.TempFileFolder;

            switch (data.FileType)
            {
                case (int)UploadFileTypeEnum.ProjectAttachment:
                    return Utility.ProjectFolder;

                case (int)UploadFileTypeEnum.MaintainPhoto:
                    return Utility.MaintainJournalFolder;

                case (int)UploadFileTypeEnum.ProjectPhoto:
                    return Utility.ProjectJournalFolder;

                case (int)UploadFileTypeEnum.EmergencyAttachment:
                    return Utility.EmergencyFolder;

                default:
                    return Utility.TempFileFolder;
            }
        }

        private static void UpdateDatabase(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            if(!data.OwnerID.HasValue)
            {
                SaveTempFile(fileID, data, fileInfo);
                return;
            }

            switch (data.FileType)
            {
                case (int) UploadFileTypeEnum.ProjectAttachment:
                    SaveProjectAttachment(fileID, data, fileInfo);
                    break;
                case (int) UploadFileTypeEnum.MaintainPhoto:
                    SaveMaintainPhoto(fileID, data, fileInfo);
                    break;
                case (int) UploadFileTypeEnum.ProjectPhoto:
                    SaveProjectPhoto(fileID, data, fileInfo);
                    break;
                case (int)UploadFileTypeEnum.EmergencyAttachment:
                    SaveEmergencyAttachment(fileID, data, fileInfo);
                    break;
                default:
                    SaveTempFile(fileID, data, fileInfo);
                    break;
            }
        }

        private static void SaveTempFile(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            using (var context = new SausageEntities())
            {
                var uploadTempFile = new UploadTempFile();
                uploadTempFile.FileID = fileID;
                uploadTempFile.FileName = data.DisplayName.Trim();
                uploadTempFile.FileExtension = fileInfo.Extension;
                uploadTempFile.Memo = data.Memo;
                uploadTempFile.UploadTime = DateTime.Now;
                uploadTempFile.IsOpen = data.IsOpen;
                context.AddToUploadTempFile(uploadTempFile);
                context.SaveChanges();
            }
        }

        private static void SaveProjectPhoto(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            using (var context = new SausageEntities())
            {
                var projectPhoto = new ProjectPhoto();
                projectPhoto.PhotoID = fileID;
                projectPhoto.JournalID = data.OwnerID.Value;
                projectPhoto.PhotoName = data.DisplayName.Trim();
                projectPhoto.FileExtension = fileInfo.Extension;
                projectPhoto.Memo = data.Memo;
                context.AddToProjectPhoto(projectPhoto);
                context.SaveChanges();
            }
        }

        private static void SaveMaintainPhoto(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            using (var context = new SausageEntities())
            {
                var maintainPhoto = new MaintainPhoto();
                maintainPhoto.PhotoID = fileID;
                maintainPhoto.JournalID = data.OwnerID.Value;
                maintainPhoto.PhotoName = data.DisplayName.Trim();
                maintainPhoto.FileExtension = fileInfo.Extension;
                maintainPhoto.Memo = data.Memo;
                context.AddToMaintainPhoto(maintainPhoto);
                context.SaveChanges();
            }
        }

        private static void SaveProjectAttachment(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            using (var context = new SausageEntities())
            {
                var attachment = new ProjectAttachment();
                attachment.AttachmentID = fileID;
                attachment.ProjectID = data.OwnerID.Value;
                attachment.OrganizationID = Helper.CurrentPrincipal.User.OrganizationID;
                attachment.AttachmentName = data.DisplayName.Trim();
                attachment.FileExtension = fileInfo.Extension;
                attachment.IsOpen = data.IsOpen;
                context.AddToProjectAttachment(attachment);
                context.SaveChanges();
            }
        }

        private static void SaveEmergencyAttachment(Guid fileID, UploadFileModel data, FileInfo fileInfo)
        {
            using (var context = new SausageEntities())
            {
                var emergencyAttachment = new EmergencyAttachment();
                emergencyAttachment.AttachmentID = fileID;
                emergencyAttachment.EmergencyID = data.OwnerID.Value;
                emergencyAttachment.AttachmentName = data.DisplayName.Trim();
                emergencyAttachment.FileExtension = fileInfo.Extension;
                context.AddToEmergencyAttachment(emergencyAttachment);
                context.SaveChanges();
            }
        }

        private static void CleanDirtyFile()
        {
            using (var context = new SausageEntities())
            {
                var endDate = DateTime.Now.AddDays(-1);
                var list = context.UploadTempFile.Where(item => item.UploadTime < endDate).ToList();
                try
                {
                    foreach (var uploadTempFile in list)
                    {

                        string savePath = string.Concat(HttpContext.Current.Server.MapPath(Utility.TempFileFolder),
                                                        Path.DirectorySeparatorChar, uploadTempFile.FileID,
                                                        uploadTempFile.FileExtension);
                        if (File.Exists(savePath))
                            File.Delete(savePath);

                        context.DeleteObject(uploadTempFile);
                    }
                    context.SaveChanges();
                }
                catch
                {
                    // do nothing.
                }
            }
        }
    }
}
